home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / jclean.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-26  |  26.1 KB  |  955 lines

  1. /* 
  2.  * jclean.c --
  3.  *
  4.  *    Write full tape buffers to archive device.
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  * Quote:
  16.  *      If you understand, things are as they are.
  17.  *      If you do not understand, things are as they are.
  18.  *      -- Gensha, Zen Master
  19.  *
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/jclean.c,v 1.0 91/01/07 18:02:37 mottsmth Exp $ SPRITE (Berkeley)";
  24. #endif /* not lint */
  25.  
  26. #include "jaquith.h"
  27. #include "option.h"
  28. #include "jcleanInt.h"
  29.  
  30. typedef struct MgrData {
  31.     int sock;
  32.     int volId;
  33.     int stream;
  34.     int mgrPort;
  35.     char *mgrServer;
  36. } MgrData;
  37.  
  38. static void ProcessArchive _ARGS_ ((char *archPath, int tBufId));
  39. static int  ProcessTBuf    _ARGS_ ((char *archPath, int tBufId,
  40.                     MetaInfo *metaInfoPtr,
  41.                     VolInfo *volInfoPtr,
  42.                     FILE *volStream,
  43.                     int outStream));
  44. static int  PrepareVolume  _ARGS_ ((VolInfo *volInfoPtr,
  45.                     MetaInfo *metaInfoPtr, int tBufId,
  46.                     MgrData *mgrDataPtr, char *archPath,
  47.                     FILE *volStream));
  48. static int  MgrAcquire     _ARGS_ ((MgrData *mgrDataPtr));
  49. static int  MgrRelease     _ARGS_ ((MgrData *mgrDataPtr));
  50. static int  PrepareHdrFile _ARGS_ ((int stream, MetaInfo *metaInfoPtr,
  51.                     int tBufId, char *archPath));
  52. static int  PrepareBufFile _ARGS_ ((int stream, MetaInfo *metaInfoPtr,
  53.                     int tBufId, char *archPath));
  54. static void MakeSpace      _ARGS_ ((char *archPath));
  55. static int  LogTBufBatch   _ARGS_ ((int volStream, Volinfo *volInfoPtr,
  56.                     int firstTBuf, int lastTBuf));
  57. static int  AssignNewVolume _ARGS_ (());
  58.  
  59.  
  60. static char printBuf[T_MAXSTRINGLEN];
  61. static char *logPath;         /* pathname of log file */
  62. static FILE *memDbg = NULL;   /* stream for memory tracing */
  63. static char archName[T_MAXSTRINGLEN];
  64.  
  65. int jDebug;                   /* Internal debugging only */
  66. int syserr = 0;               /* Our personal record of errno */
  67.  
  68. Parms parms = {
  69.     DEF_ARCHLIST,
  70.     DEF_ROOT,
  71.     DEF_USER,
  72.     DEF_SERVER,
  73.     DEF_DEBUG,
  74.     DEF_TBUFID,
  75.     DEF_NEWVOL,
  76.     DEF_DISKLOW,
  77.     DEF_DISKHIGH
  78. };
  79.  
  80. Option optionArray[] = {
  81.     {OPT_STRING, "arch", (char *)&parms.arch, "logical archive name"},
  82.     {OPT_STRING, "root", (char *)&parms.root, "root of archive tree"},
  83.     {OPT_STRING, "username", (char *)&parms.userName, "User issuing request"},
  84.     {OPT_STRING, "hostname", (char *)&parms.hostName, "Machine name"},
  85.     {OPT_INT, "debug", (char *)&parms.debug, "Enable debugging"},
  86.     {OPT_INT, "tbufid", (char *)&parms.tBufId, "tbuf id to clean"},
  87.     {OPT_INT, "newvol", (char *)&parms.newVol, "Start a new volume"},
  88.     {OPT_INT, "disklow", (char *)&parms.diskLow, "Low percent disk full"},
  89.     {OPT_INT, "diskhigh", (char *)&parms.diskHigh, "High percent disk full"}
  90. };
  91. int numOptions = sizeof(optionArray) / sizeof(Option);
  92.  
  93.  
  94.  
  95. /*
  96.  *----------------------------------------------------------------------
  97.  *
  98.  * main --
  99.  *
  100.  *    Main driver for cleaner program.
  101.  *
  102.  * Results:
  103.  *    none.
  104.  *
  105.  * Side effects:
  106.  *    Sends tape buffers to device
  107.  *
  108.  *----------------------------------------------------------------------
  109.  */
  110.  
  111. int
  112. main(argc, argv)
  113.     int argc;
  114.     char *argv[];
  115. {
  116.     int retCode;
  117.     int type;
  118.     DIR *rootDirPtr;
  119.     DirObject *entryPtr;
  120.     struct stat statBuf;
  121.     char archPath[T_MAXPATHLEN];
  122.     static struct timeval curTime;    
  123.  
  124. /*    memDbg = fopen("jclean.mem","w"); */
  125.     MEM_CONTROL(8192, memDbg, TRACEMEM+TRACECALLS+CHECKALLBLKS, 4096);
  126.  
  127.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  128.  
  129.     jDebug = parms.debug;
  130.  
  131.     if ((rootDirPtr=(DIR *)opendir(parms.root)) == (DIR *) NULL) {
  132.     return 0;
  133.     }
  134.  
  135.     while ((entryPtr=readdir(rootDirPtr)) != (DirObject *)NULL) {
  136.     if ((*entryPtr->d_name != '.') &&
  137.         (Str_Match(entryPtr->d_name, parms.arch))) {
  138.         strcpy(archPath, parms.root);
  139.         strcat(archPath, "/");
  140.         strcat(archPath, entryPtr->d_name);
  141.         stat(archPath, &statBuf);
  142.         type = statBuf.st_mode & S_IFMT;
  143.         if (type == S_IFDIR) {
  144.             strcpy(archName, entryPtr->d_name);
  145.         ProcessArchive(archPath, parms.tBufId);
  146.         }
  147.     }
  148.     }
  149.  
  150.     closedir(rootDirPtr);
  151.  
  152.     /* Clean out any old buffers, if diskspace is tight */
  153.     MakeSpace();
  154.  
  155.     return retCode;
  156. }
  157.  
  158.  
  159. /*
  160.  *----------------------------------------------------------------------
  161.  *
  162.  * ProcessArchive -- 
  163.  *
  164.  *    Write out the buffers for specified archive
  165.  *
  166.  * Results:
  167.  *    none.
  168.  *
  169.  * Side effects:
  170.  *    May issue mount requests to device synchronizer
  171.  *
  172.  *----------------------------------------------------------------------
  173.  */
  174.  
  175. static void
  176. ProcessArchive(archPath, requestedTBufId)
  177.     char *archPath;           /* Pathname to desired archive. */
  178.     int requestedTBufId;      /* desired buffer. -1 if unspecified */
  179. {
  180.     VolInfo volInfo;
  181.     MetaInfo metaInfo;
  182.     int tBufId;
  183.     int curTBufId;
  184.     int nextLogTBuf;
  185.     int retCode = T_SUCCESS;
  186.     int tBufCnt;
  187.     int firstTBuf;
  188.     int lastTBuf = -1;
  189.     FILE *volStream;
  190.     FILE *metaStream;
  191.     Lock_Handle lockHandle;
  192.     MgrData mgrData;
  193.     ArchConfig archConfig;
  194.     int i;
  195.  
  196.     mgrData.sock = -1;
  197.     mgrData.volId = -1;
  198.     mgrData.stream = -1;
  199.  
  200.     /* Try to get exclusive cleaner lock, else retire */
  201.     if ((volStream=Admin_OpenVolInfo(archPath, &lockHandle))
  202.     == (FILE *)NULL) {
  203.     return;
  204.     }
  205.  
  206.     logPath = Str_Cat(3, archPath, "/", ARCHLOGFILE);
  207.     Log_AtomicEvent("Jclean", "Cleaning...", logPath);
  208.  
  209.     if (Admin_ReadArchConfig(archPath, &archConfig) != T_SUCCESS) {
  210.     sprintf(printBuf, "Couldn't read archive config file. errno %d\n",
  211.         syserr);
  212.     Log_AtomicEvent("Jclean", printBuf, logPath);
  213.     }
  214.     mgrData.mgrPort = archConfig.mgrPort;
  215.     mgrData.mgrServer = archConfig.mgrServer;
  216.  
  217.     if (Admin_ReadVolInfo(volStream, &volInfo) != T_SUCCESS) {
  218.     sprintf(printBuf, "Couldn't read volinfo file. errno %d\n",
  219.         syserr);
  220.     Log_AtomicEvent("Jclean", printBuf, logPath);
  221.     }
  222.     firstTBuf = nextLogTBuf = volInfo.lastTBuf+1;
  223.  
  224.     /*
  225.      * Now repeatedly run through files until there's nothing
  226.      * left to clean.  
  227.      */
  228.     do {
  229.     if (Admin_GetCurTBuf(archPath, &curTBufId) != T_SUCCESS) {
  230.         sprintf(printBuf, "Couldn't read current tbufd. errno %d\n",
  231.             syserr);
  232.         Log_AtomicEvent("Jclean", printBuf, logPath);
  233.         break;
  234.     }
  235.     tBufCnt = 0;
  236.     if (volInfo.lastTBuf >= curTBufId) {
  237.         sprintf(printBuf, "Error: last tBuf %d, cur tBuf %d\n",
  238.             volInfo.lastTBuf,curTBufId);
  239.         Log_AtomicEvent("Jclean", printBuf, logPath);
  240.     }
  241.     for (tBufId=volInfo.lastTBuf+1; tBufId<curTBufId; tBufId++) {
  242.         metaStream = Admin_OpenMetaInfo(archPath, tBufId);
  243.         Admin_ReadMetaInfo(metaStream, &metaInfo);
  244.         Admin_CloseMetaInfo(metaStream);
  245.         if ((retCode=PrepareVolume(&volInfo, &metaInfo, tBufId,
  246.              &mgrData,archPath, volStream)) != T_SUCCESS) {
  247.         sprintf(printBuf,"RetCode %d from PrepareVolume\n", retCode);
  248.         Log_AtomicEvent("Jclean", printBuf, logPath);
  249.         if (jDebug) {
  250.             fprintf(stderr,"%s", printBuf);
  251.         }
  252.         break;
  253.         }
  254.         if ((retCode=ProcessTBuf(archPath, tBufId, &metaInfo,&volInfo,
  255.                  volStream, mgrData.stream)) != T_SUCCESS) {
  256.         sprintf(printBuf,"RetCode %d from ProcessTBuf\n", retCode);
  257.         Log_AtomicEvent("Jclean", printBuf, logPath);
  258.         if (jDebug) {
  259.             fprintf(stderr,"(%d) %s", Time_Stamp(), printBuf);
  260.         }
  261.         break;
  262.         }
  263.         if ((tBufId-nextLogTBuf+1 >= LOGFREQ) &&
  264.         ((nextLogTBuf=LogTBufBatch(volStream, &volInfo,
  265.                        nextLogTBuf, tBufId)) < 0)) {
  266.             break;
  267.         }
  268.         tBufCnt++;
  269.         lastTBuf = tBufId;
  270.     }
  271.     } while ((tBufCnt > 0) && (retCode == T_SUCCESS));
  272.  
  273.     if ((lastTBuf >= nextLogTBuf) &&
  274.         ((nextLogTBuf=LogTBufBatch(volStream, &volInfo,
  275.                    nextLogTBuf, lastTBuf)) < 0)) {
  276.         lastTBuf = nextLogTBuf-1;
  277.     }
  278.  
  279.     Admin_CloseVolInfo(&lockHandle, volStream);
  280.     MgrRelease(&mgrData);
  281.  
  282.     if (lastTBuf == -1) {
  283.     sprintf(printBuf, "No tbufs cleaned. retCode %d\n", retCode);
  284.     } else {
  285.         sprintf(printBuf, "Cleaned tbuf.%d to tbuf.%d. retCode %d\n",
  286.             firstTBuf, lastTBuf, retCode);
  287.     }
  288.     Log_AtomicEvent("Jclean", printBuf, logPath);
  289.     if (jDebug) {
  290.     fprintf(stderr, "(%d) %s", Time_Stamp(), printBuf);
  291.     }
  292.  
  293.     MEM_FREE("ProcessArchive", logPath);
  294.     MEM_REPORT("jclean", ALLROUTINES, SORTBYOWNER);
  295. }
  296.  
  297.  
  298.  
  299. /*
  300.  *----------------------------------------------------------------------
  301.  *
  302.  * ProcessTBuf -- 
  303.  *
  304.  *    Write a tbuf out to physical volume.
  305.  *
  306.  * Results:
  307.  *    none.
  308.  *
  309.  * Side effects:
  310.  *    Consumes volume space.  Updating of volinfo file is not done
  311.  *      for each tbuf individually, but in LOGFREQ batches for performance.
  312.  *
  313.  *----------------------------------------------------------------------
  314.  */
  315.  
  316. static int
  317. ProcessTBuf(archPath, tBufId, metaInfoPtr, volInfoPtr,
  318.         volStream, outStream)
  319.     char *archPath;           /* archive path */
  320.     int tBufId;               /* buffer id # */
  321.     MetaInfo *metaInfoPtr;    /* buffer information */
  322.     VolInfo *volInfoPtr;      /* volume information */
  323.     FILE *volStream;          /* active vol info stream */
  324.     int outStream;            /* active output stream */
  325. {
  326.     int tBufSize;
  327.     int tHdrSize;
  328.     char buf[T_TARSIZE];
  329.     int sock;
  330.     int retCode = T_SUCCESS;
  331.     int tBufStream;
  332.     int tHdrStream;
  333.     int len;
  334.     VolStatus volStatus;
  335.     int totalLen;
  336.  
  337.     TBuf_Open(archPath, tBufId, &tBufStream, &tHdrStream, O_RDWR);
  338.  
  339.     if ((tHdrSize=PrepareHdrFile(tHdrStream, metaInfoPtr, tBufId, archPath)) < 0) {
  340.         sprintf(printBuf, "Couldn't form hdr file. errno %d\n", syserr);
  341.         Log_AtomicEvent("Jclean", printBuf, logPath);
  342.     return T_FAILURE;
  343.     }
  344.  
  345.     if ((tBufSize=PrepareBufFile(tBufStream, metaInfoPtr, tBufId, archPath)) < 0) {
  346.         sprintf(printBuf, "Couldn't form buf file. errno %d\n", syserr);
  347.         Log_AtomicEvent("Jclean", printBuf, logPath);
  348.     return T_FAILURE;
  349.     }
  350.  
  351.     /* Remaining volSpace will be decremented by this amount, */
  352.     /* unless Dev_GetVolStatus can tell us more accurately. */
  353.     totalLen = ((tHdrSize+tBufSize+(2*T_FILEMARKSIZE))>>10) + 1;
  354.  
  355.     if (jDebug) {
  356.         fprintf(stderr,"(%d) jclean writing %d: hdr %d, buf %d\n",
  357.         Time_Stamp(), tBufId, tHdrSize, tBufSize);
  358.     }
  359.  
  360.     while (tHdrSize > 0) {
  361.     len = (tHdrSize > sizeof(buf)) ? sizeof(buf) : tHdrSize;
  362.     if (read(tHdrStream, buf, len) != len) {
  363.         sprintf(printBuf, "Short thdr read. errno %d\n", errno);
  364.         Log_AtomicEvent("Jclean", printBuf, logPath);
  365.         if (jDebug) {
  366.             fprintf(stderr, printBuf);
  367.         }
  368.         retCode = T_IOFAILED;
  369.         break;
  370.     }
  371.     if (Dev_WriteVolume(outStream, buf, sizeof(buf)) != sizeof(buf)) {
  372.         sprintf(printBuf, "Short thdr write. errno %d\n", syserr);
  373.         Log_AtomicEvent("Jclean", printBuf, logPath);
  374.         if (jDebug) {
  375.             fprintf(stderr, printBuf);
  376.         }
  377.         retCode = T_IOFAILED;
  378.         break;
  379.     }
  380.     tHdrSize -= len;
  381.     }
  382.     if (Dev_WriteEOF(outStream, 1) != T_SUCCESS) {
  383.     sprintf(printBuf, "EOF after thdr failed. errno %d\n", syserr);
  384.     Log_AtomicEvent("Jclean", printBuf, logPath);
  385.     if (jDebug) {
  386.         fprintf(stderr, printBuf);
  387.     }
  388.     retCode = T_IOFAILED;
  389.     }
  390.  
  391.     while ((retCode == T_SUCCESS) && (tBufSize > 0)) {
  392.     len = (tBufSize > sizeof(buf)) ? sizeof(buf) : tBufSize;
  393.     if (read(tBufStream, buf, len) != len) {
  394.         sprintf(printBuf, "Short tbuf read. errno %d\n", errno);
  395.         Log_AtomicEvent("Jclean", printBuf, logPath);
  396.         if (jDebug) {
  397.             fprintf(stderr, printBuf);
  398.         }
  399.         retCode = T_IOFAILED;
  400.         break;
  401.     }
  402.         if (Dev_WriteVolume(outStream, buf, sizeof(buf)) != sizeof(buf)) {
  403.         sprintf(printBuf, "Short tbuf write. errno %d\n", syserr);
  404.         Log_AtomicEvent("Jclean", printBuf, logPath);
  405.         if (jDebug) {
  406.             fprintf(stderr, printBuf);
  407.         }
  408.         retCode = T_IOFAILED;
  409.         break;
  410.     }
  411.     tBufSize -= len;
  412.     }
  413.     if (Dev_WriteEOF(outStream, 1) != T_SUCCESS) {
  414.     sprintf(printBuf, "EOF after tbuf failed. errno %d\n", syserr);
  415.     Log_AtomicEvent("Jclean", printBuf, logPath);
  416.     if (jDebug) {
  417.         fprintf(stderr, printBuf);
  418.     }
  419.     retCode = T_IOFAILED;
  420.     }
  421.  
  422.     TBuf_Close(tBufStream, tHdrStream, -1);
  423.  
  424.     volStatus.remaining = volInfoPtr->volSpace - totalLen;
  425.     if (Dev_GetVolStatus(outStream, &volStatus) != T_SUCCESS) {
  426.     sprintf(printBuf, "Couldn't get volume status. errno %d\n", syserr);
  427.     Log_AtomicEvent("Jclean", printBuf, logPath);
  428.     }
  429.     if (retCode == T_SUCCESS) {
  430.     volInfoPtr->lastTBuf = tBufId;
  431.     volInfoPtr->filemark += 2;
  432.     volInfoPtr->volSpace = volStatus.remaining;
  433.     }
  434.     return retCode;
  435. }
  436.  
  437.  
  438. /*
  439.  *----------------------------------------------------------------------
  440.  *
  441.  * LogTBufBatch -- 
  442.  *
  443.  *    Update volinfo log to acknowledge procesing of buffer batch.
  444.  *
  445.  * Results:
  446.  *    none.
  447.  *
  448.  *----------------------------------------------------------------------
  449.  */
  450.  
  451. static int
  452. LogTBufBatch(volStream, volInfoPtr, firstTBuf, lastTBuf)
  453.     int volStream;            /* volinfo file */
  454.     VolInfo *volInfoPtr;      /* log record data */
  455.     int firstTBuf;            /* first tbuf Id in batch */
  456.     int lastTBuf;             /* last tbuf Id in batch */
  457. {
  458.     if (Admin_WriteVolInfo(volStream, volInfoPtr) != T_SUCCESS) {
  459.     sprintf(printBuf,"Couldn't update log: tbuf.%d to tbuf.%d\n",
  460.         firstTBuf, lastTBuf);
  461.     Log_AtomicEvent("Jclean", printBuf, logPath);
  462.     if (jDebug) {
  463.         fprintf(stderr, "%s", printBuf);
  464.     }
  465.     return -1;
  466.     } else {
  467.     TBuf_Delete(parms.root, archName, firstTBuf, lastTBuf);
  468.     sprintf(printBuf,"Deleted: tbuf.%d to tbuf.%d\n",
  469.         firstTBuf, lastTBuf);
  470.     Log_AtomicEvent("Jclean", printBuf, logPath);
  471.     if (jDebug) {
  472.         fprintf(stderr, "%s", printBuf);
  473.     }
  474.         return lastTBuf+1;
  475.     }
  476. }
  477.  
  478.  
  479. /*
  480.  *----------------------------------------------------------------------
  481.  *
  482.  * PrepareVolume
  483.  *
  484.  *    Get a new volume and seek to proper filemark
  485.  *
  486.  * Results:
  487.  *    return code
  488.  *
  489.  * Side effects:
  490.  *    Causes socket chatter to jukebox mgr.
  491.  *
  492.  * Note:
  493.  *      To minimize tape motion, this thing remembers
  494.  *      the current volume and does nothing if new one's the same.
  495.  *
  496.  *----------------------------------------------------------------------
  497.  */
  498.  
  499. static int 
  500. PrepareVolume(volInfoPtr, metaInfoPtr, tBufId, mgrDataPtr,
  501.           archPath, volStream)
  502.     VolInfo *volInfoPtr;      /* current volume situation */
  503.     MetaInfo *metaInfoPtr;    /* current buffer situation */
  504.     int tBufId;               /* current buffer number */
  505.     MgrData *mgrDataPtr;      /* active info for jmgr */
  506.     char *archPath;           /* current archive path */
  507.     FILE *volStream;          /* current vol info stream */
  508. {
  509.     int retCode = T_SUCCESS;
  510.     int totalLen;
  511.  
  512.     totalLen = ((metaInfoPtr->tHdrSize+
  513.          metaInfoPtr->tBufSize+
  514.          (2*T_FILEMARKSIZE))>>10) + 1;
  515.  
  516.     if ((volInfoPtr->volId == -1) ||
  517.     ((parms.newVol) && (parms.tBufId == tBufId)) ||
  518.     (totalLen+SLOPSPACEK > volInfoPtr->volSpace)) {
  519.     if ((volInfoPtr->volId=AssignNewVolume()) == -1) {
  520.         return T_NOVOLUME;
  521.     }
  522.     volInfoPtr->filemark = 0;
  523.     volInfoPtr->volSpace = T_VOLSIZEK;
  524.     if ((Admin_AddTBufId(archPath, volInfoPtr->volId, tBufId)
  525.          != T_SUCCESS) ||
  526.         (Admin_WriteVolInfo(volStream, volInfoPtr) != T_SUCCESS)) {
  527.         sprintf(printBuf, "Meta info failed for new volume %d\n",
  528.             volInfoPtr->volId);
  529.         Log_AtomicEvent("Jclean", printBuf, logPath);
  530.         return T_ADMFAILED;
  531.     }
  532.     }
  533.  
  534.     /* If same volume as before, do nothing */
  535.     if (volInfoPtr->volId == mgrDataPtr->volId) {
  536.     return retCode;
  537.     }
  538.  
  539.     /* else release old volume if any */
  540.     MgrRelease(mgrDataPtr);
  541.  
  542.     /* acquire the new volume */
  543.     mgrDataPtr->volId = volInfoPtr->volId;
  544.     if (MgrAcquire(mgrDataPtr) != T_SUCCESS) {
  545.     return T_FAILURE;
  546.     }
  547.  
  548.     sprintf(printBuf, "Seeking fd %d past filemark %d\n",
  549.         mgrDataPtr->stream, volInfoPtr->filemark);
  550.     Log_AtomicEvent("Jclean", printBuf, logPath);
  551.     if (jDebug) {
  552.     fprintf(stderr,"(%d) %s", Time_Stamp(), printBuf);
  553.     }
  554.  
  555.     if (Dev_SeekVolume(mgrDataPtr->stream, volInfoPtr->filemark,
  556.                DEV_ABSOLUTE) != T_SUCCESS) {
  557.     sprintf(printBuf, "Couldn't seek to block %d: errno %d\n",
  558.         volInfoPtr->filemark, syserr);
  559.     Log_AtomicEvent("Jclean", printBuf, logPath);
  560.     return T_IOFAILED;
  561.     }
  562.     return retCode;
  563. }
  564.  
  565.  
  566. /*
  567.  *----------------------------------------------------------------------
  568.  *
  569.  * AssignNewVolume --
  570.  *
  571.  *    Assign and verify new volume Id
  572.  *
  573.  * Results:
  574.  *    New volume Id or -1
  575.  *
  576.  * Side effects:
  577.  *    Updates free volume list
  578.  *
  579.  *----------------------------------------------------------------------
  580.  */
  581.  
  582. static int
  583. AssignNewVolume()
  584. {
  585.     int volId;
  586.     int retCode;
  587.     VolOwner *volOwnerPtr;
  588.  
  589.     while (1) {
  590.     volId = -1;
  591.     if ((retCode=Admin_GetFreeVol(parms.root, &volId)) != T_SUCCESS) {
  592.         if (retCode == T_NOVOLUME) {
  593.         sprintf(printBuf, "No free volumes!\n");
  594.         } else {
  595.         sprintf(printBuf, "Couldn't get new volume: errno %d\n",
  596.             syserr);
  597.         }
  598.         Log_AtomicEvent("Jclean", printBuf, logPath);
  599.         return -1;
  600.     }
  601.     /* Ok, got a volume, now do a sanity check */
  602.     volOwnerPtr = Admin_FindVolOwner(volId, parms.root, "*.arch");
  603.     if (volOwnerPtr->owner == NULL) {
  604.         sprintf(printBuf, "Assigned new volume %d\n", volId);
  605.         Log_AtomicEvent("Jclean", printBuf, logPath);
  606.         return volId;
  607.     } else {
  608.         sprintf(printBuf, "Oh my. Assigned volume %d, but it's already in use by %s. Retrying...\n",
  609.             volId, volOwnerPtr->owner);
  610.         Log_AtomicEvent("Jclean", printBuf, logPath);
  611.     }
  612.     }
  613. }
  614.  
  615.  
  616.  
  617. /*
  618.  *----------------------------------------------------------------------
  619.  *
  620.  * MgrAcquire
  621.  *
  622.  *    Talk to jukebox manager to acquire a volume
  623.  *
  624.  * Results:
  625.  *    return code
  626.  *
  627.  * Side effects:
  628.  *    Acquires or releases volume
  629.  *
  630.  *----------------------------------------------------------------------
  631.  */
  632.  
  633. static int
  634. MgrAcquire(mgrDataPtr)
  635.     MgrData *mgrDataPtr;      /* jmgr status info */
  636. {
  637.     int retCode = T_SUCCESS;
  638.     char devName[T_MAXPATHLEN];
  639.     char *devNamePtr = devName;
  640.     int status =T_SUCCESS;
  641.     int sleepSecs = 5;
  642.     int retryCnt = 0;
  643.  
  644.     if ((mgrDataPtr->sock=
  645.      Sock_SetupSocket(mgrDataPtr->mgrPort,
  646.               mgrDataPtr->mgrServer, 0)) == -1) {
  647.     sprintf(printBuf, "Cleaner couldn't connect to jmgr at %s port %d. errno %d\n",
  648.         mgrDataPtr->mgrServer, mgrDataPtr->mgrPort, syserr);
  649.     Log_AtomicEvent("Jclean", printBuf, logPath);
  650.     if (Utils_SendMail(ARCHMASTER, printBuf, "alert") != 0) {
  651.         sprintf(printBuf, "Got return code %d mailing alert to %s\n",
  652.             retCode, ARCHMASTER);
  653.         Log_AtomicEvent("Jclean", printBuf, logPath);
  654.     }
  655.     return T_FAILURE;
  656.     }
  657.  
  658.     retCode = Sock_WriteString(mgrDataPtr->sock, parms.userName, 0);
  659.     retCode += Sock_WriteInteger(mgrDataPtr->sock, S_CMDLOCK);
  660.     retCode += Sock_WriteInteger(mgrDataPtr->sock, mgrDataPtr->volId);
  661.     retCode += Sock_ReadInteger(mgrDataPtr->sock, &status);
  662.  
  663.     if ((retCode != T_SUCCESS) || (status != T_SUCCESS)) {
  664.     sprintf(printBuf,"Couldn't acquire vol %d. Status %d, errno %d\n",
  665.         mgrDataPtr->volId, status, syserr);
  666.     Log_AtomicEvent("Jclean", printBuf, logPath);
  667.     return T_FAILURE;
  668.     }
  669.  
  670.     Sock_ReadString(mgrDataPtr->sock, &devNamePtr, 0);
  671.     sprintf(printBuf, "Acquired vol %d in device %s\n",
  672.         mgrDataPtr->volId, devName);
  673.     Log_AtomicEvent("Jclean", printBuf, logPath);
  674.     if (jDebug) {
  675.     fprintf(stderr, "(%d) %s", Time_Stamp(), printBuf);
  676.     }
  677.  
  678.     /* Must sleep here, waiting for drive to spin up...*/
  679.     while (((mgrDataPtr->stream=Dev_OpenVolume(devName, O_RDWR)) == -1) &&
  680.        (retryCnt++ < 10)) {
  681.     sleep(sleepSecs);
  682.     }
  683.     if (mgrDataPtr->stream == -1) {
  684.     sprintf(printBuf, "Couldn't open device %s. errno %d\n",
  685.         devName, syserr);
  686.     Log_AtomicEvent("Jclean", printBuf, logPath);
  687.     return T_IOFAILED;
  688.     }
  689.     if (jDebug) {
  690.     fprintf(stderr, "(%d) Opened device %s, fd %d.\n",
  691.         Time_Stamp(), devName, mgrDataPtr->stream);
  692.     }
  693.  
  694.     return retCode;
  695. }
  696.  
  697.  
  698. /*
  699.  *----------------------------------------------------------------------
  700.  *
  701.  * MgrRelease
  702.  *
  703.  *    Talk to jukebox manager to release a volume
  704.  *
  705.  * Results:
  706.  *    return code
  707.  *
  708.  * Side effects:
  709.  *    Drops connection to jmgr
  710.  *
  711.  *----------------------------------------------------------------------
  712.  */
  713.  
  714. static int
  715. MgrRelease(mgrDataPtr)
  716.     MgrData *mgrDataPtr;      /* jmgr status info */
  717. {
  718.     int retCode = T_SUCCESS;
  719.     int status =T_SUCCESS;
  720.  
  721.     if (mgrDataPtr->sock == -1) {
  722.     return;
  723.     }
  724.  
  725.     sprintf(printBuf, "Releasing vol %d.\n", mgrDataPtr->volId);
  726.     Log_AtomicEvent("Jclean", printBuf, logPath);
  727.     if (jDebug) {
  728.     fprintf(stderr, "%s", printBuf);
  729.     }
  730.  
  731.     retCode = Sock_WriteString(mgrDataPtr->sock, parms.userName, 0);
  732.     retCode += Sock_WriteInteger(mgrDataPtr->sock, S_CMDFREE);
  733.     retCode += Sock_WriteInteger(mgrDataPtr->sock, mgrDataPtr->volId);
  734.     retCode += Sock_ReadInteger(mgrDataPtr->sock, &status);
  735.     if ((retCode != T_SUCCESS) || (status != T_SUCCESS)) {
  736.     sprintf(printBuf,"Couldn't release vol %d. Status %d, errno %d\n",
  737.         mgrDataPtr->volId, status, syserr);
  738.     Log_AtomicEvent("Jclean", printBuf, logPath);
  739.     }
  740.  
  741.     close(mgrDataPtr->sock);
  742.     Dev_CloseVolume(mgrDataPtr->stream);
  743.  
  744.     mgrDataPtr->sock = -1;
  745.     mgrDataPtr->volId = -1;
  746.     mgrDataPtr->stream = -1;
  747.  
  748.     return retCode;
  749. }
  750.  
  751.  
  752.  
  753. /*
  754.  *----------------------------------------------------------------------
  755.  *
  756.  * PrepareHdrFile --
  757.  *
  758.  *    Build header file corresponding to user file
  759.  *
  760.  * Results:
  761.  *    Byte count of file.
  762.  *
  763.  * Side effects:
  764.  *    Writes data out to thdr.<tbufID>
  765.  *
  766.  *----------------------------------------------------------------------
  767.  */
  768.  
  769. static int
  770. PrepareHdrFile(tHdrStream, metaInfoPtr, tBufId, archPath)
  771.     int tHdrStream;           /* outgoing descriptor */
  772.     MetaInfo *metaInfoPtr;    /* meta data */
  773.     int tBufId;               /* Number of this buffer */
  774.     char *archPath;           /* Full path of archive */
  775. {
  776.     static T_FileStat hdrStatInfo =
  777.     {NULL, "", "root", "root", "", "",
  778.          0, 0, 0, 0, 0, 0, 0100600, 0, 0, 0, 0, 0};
  779.     char fullName[T_MAXPATHLEN];
  780.     static int myUid = -1;
  781.     static int myGid = -1;
  782.     static char *myName;
  783.     static char *myGroup;
  784.     int padCnt;
  785.     int termCnt;
  786.     struct stat unixStatBuf;
  787.     int tHdrSize = metaInfoPtr->tHdrSize;
  788.  
  789.     if (myUid == -1) {
  790.     myUid = (int) geteuid();
  791.     myGid = (int) getegid();
  792.     myName = Utils_GetLoginByUid(myUid);
  793.     myGroup = Utils_GetGroupByGid(myGid);
  794.     }
  795.  
  796.     /* Verify header file against meta info */
  797.     sprintf(printBuf, "%s/thdr.%d%c", archPath, tBufId, '\0');
  798.     stat(printBuf, &unixStatBuf);
  799.     if (unixStatBuf.st_size > tHdrSize) {
  800.         sprintf(printBuf, "Truncating %s/thdr.%d from %d to %d\n",
  801.         archPath, tBufId, unixStatBuf.st_size, tHdrSize);
  802.     Log_AtomicEvent("Jclean", printBuf, logPath);
  803.     if (jDebug) {
  804.         fprintf(stderr, "%s", printBuf);
  805.     }
  806.         ftruncate(tHdrStream, tHdrSize);
  807.     TBuf_Seek(tHdrStream, 0);
  808.     }
  809.  
  810.     sprintf(fullName,"%s/thdr.%d%c", archName, tBufId, '\0');
  811.     hdrStatInfo.fileName = fullName;
  812.     hdrStatInfo.vtime = Time_GetCurDate();
  813.     hdrStatInfo.mtime = hdrStatInfo.vtime;
  814.     hdrStatInfo.atime = hdrStatInfo.vtime;
  815.     hdrStatInfo.uid = myUid;
  816.     hdrStatInfo.gid = myGid;
  817.     hdrStatInfo.uname = myName;
  818.     hdrStatInfo.gname = myGroup;
  819.     hdrStatInfo.size = tHdrSize-T_TBLOCK;
  820.  
  821.     if (TBuf_WriteTarHdr(tHdrStream, &hdrStatInfo) < 1) {
  822.         fprintf(stderr,"MakeTarHdr failed\n");
  823.     return -1;
  824.     }
  825.  
  826.     if (TBuf_Seek(tHdrStream, tHdrSize) != T_SUCCESS) {
  827.         fprintf(stderr,"seek failed\n");
  828.         return -1;
  829.     }
  830.  
  831.     if ((padCnt=TBuf_Pad(tHdrStream, tHdrSize, T_TBLOCK)) < 0) {
  832.         fprintf(stderr,"pad failed\n");
  833.         syserr = errno;
  834.         return -1;
  835.     }
  836.  
  837.     tHdrSize += padCnt;
  838.     if ((termCnt=TBuf_Terminate(tHdrStream, tHdrSize)) < 0) {
  839.         fprintf(stderr,"terminate failed\n");
  840.         return -1;
  841.     }
  842.  
  843.     if (TBuf_Seek(tHdrStream, 0) != T_SUCCESS) {
  844.         fprintf(stderr,"seek 2 failed\n");
  845.         return -1;
  846.     }
  847.  
  848.     return tHdrSize+termCnt;
  849. }
  850.  
  851.  
  852. /*
  853.  *----------------------------------------------------------------------
  854.  *
  855.  * PrepareBufFile --
  856.  *
  857.  *    Make sure buffer is ready for output.
  858.  *
  859.  * Results:
  860.  *    None.
  861.  *
  862.  * Side effects:
  863.  *    May truncate buffer.
  864.  *
  865.  *----------------------------------------------------------------------
  866.  */
  867.  
  868. static int
  869. PrepareBufFile(tBufStream, metaInfoPtr, tBufId, archPath)
  870.     int tBufStream;           /* outgoing descriptor */
  871.     MetaInfo *metaInfoPtr;    /* meta data */
  872.     int tBufId;               /* Number of this buffer */
  873.     char *archPath;           /* Full path of archive */
  874. {
  875.     struct stat unixStatBuf;
  876.     int tBufSize = metaInfoPtr->tBufSize+metaInfoPtr->tBufPad;
  877.  
  878.     /* Verify buffer file against meta info */
  879.     sprintf(printBuf, "%s/tbuf.%d%c", archPath, tBufId, '\0');
  880.     stat(printBuf, &unixStatBuf);
  881.     if (unixStatBuf.st_size > tBufSize) {
  882.         sprintf(printBuf, "Truncating %s/tbuf.%d from %d to %d\n",
  883.         archPath, tBufId, unixStatBuf.st_size, metaInfoPtr->tBufSize);
  884.     Log_AtomicEvent("Jclean", printBuf, logPath);
  885.     if (jDebug) {
  886.         fprintf(stderr, "%s", printBuf);
  887.     }
  888.     TBuf_Seek(tBufStream, metaInfoPtr->tBufSize);
  889.     TBuf_Terminate(tBufStream, metaInfoPtr->tBufSize);
  890.         ftruncate(tBufStream, tBufSize);
  891.     TBuf_Seek(tBufStream, 0);
  892.     }
  893.  
  894.     return tBufSize;
  895. }
  896.  
  897.  
  898. /*
  899.  *----------------------------------------------------------------------
  900.  *
  901.  * MakeSpace --
  902.  *
  903.  *    Remove old buffers til disk usage drops below threshold.
  904.  *
  905.  * Results:
  906.  *    None.
  907.  *
  908.  * Side effects:
  909.  *    Removes buffers from disk.
  910.  *
  911.  *----------------------------------------------------------------------
  912.  */
  913.  
  914. static void
  915. MakeSpace()
  916. {
  917.     char archPath[T_MAXPATHLEN];
  918.     char deadArch[T_MAXPATHLEN];
  919.     int deadTBufId;
  920.     int curTBufId;
  921.     int percentUsed;
  922.     long blocksFree;
  923.     Lock_Handle lockHandle;
  924.     VolInfo volInfo;
  925.     FILE *volStream;
  926.  
  927.     while (1) {
  928.     Admin_GetDiskUse(parms.root, &percentUsed, &blocksFree);
  929.     if ((percentUsed < parms.diskLow) ||
  930.         (Admin_RemoveLRU(parms.root, deadArch, &deadTBufId)
  931.          != T_SUCCESS)) {
  932.         break;
  933.     } 
  934.     strcpy(archPath, parms.root);
  935.     strcat(archPath, "/");
  936.     strcat(archPath, deadArch);
  937.     if ((volStream=Admin_OpenVolInfo(archPath, &lockHandle)) != NULL) {
  938.         Admin_ReadVolInfo(volStream, &volInfo);
  939.         Admin_CloseVolInfo(&lockHandle, volStream);
  940.         if (deadTBufId <= volInfo.lastTBuf) {
  941.         sprintf(printBuf,"MakeSpace: deleting %s/tbuf.%d\n",
  942.             deadArch, deadTBufId);
  943.         strcat(archPath, "/");
  944.         strcat(archPath, ARCHLOGFILE);
  945.         Log_AtomicEvent("jclean", printBuf, archPath);
  946.         if (jDebug) {
  947.             fprintf(stderr, "%s", printBuf);
  948.         }
  949.         TBuf_Delete(parms.root, deadArch, deadTBufId, deadTBufId);
  950.         }
  951.     }
  952.     }
  953. }
  954.  
  955.